package cn.touna.jss.modules.third.gxb;

import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.properties.disconf.GongXinBaoProperties;
import cn.touna.jss.common.util.HttpUtil;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.credit.mapper.CreditQueryHistoryEntityMapper;
import cn.touna.jss.modules.third.gxb.entity.GxbDataRequest;
import cn.touna.jss.modules.third.gxb.entity.GxbRequest;
import cn.touna.jss.modules.third.gxb.entity.GxbTokenRequest;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.cache.redis.RedisCache;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.touna.loan.log.service.TracerContextUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 公信宝<br/>
 * 文档：https://doc.gxb.io/dcdoc/shu-ju-tui-song.html<br/>
 * 业务流程：app获取授权码，然后调用公信宝接口
 */
@Service
public class GongXinBaoService {

    private static final String GONGXINBAO_TOKEN = "gongxinbao_token:%s:%s";
    @Autowired
    private CreditQueryHistoryEntityMapper creditQueryHistoryEntityMapper;

    private final static String paramStr = "%s?appId=%s&timestamp=%s&sign=%s";

    @Autowired
    private GongXinBaoProperties config;

    @Autowired
    RedisCache redisCache;


    private static final Logger logger = LogManager.getLogger(GongXinBaoService.class);


    @ApiMapping(value = "gongxinbao.getToken",desc = "公信宝.获取token")
    public Response getToken(GxbTokenRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null){
            return response;
        }

        //组装参数
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sequenceNo =  TracerContextUtil.getTraceId();
        JSONObject reqObj = new JSONObject();
        reqObj.put("appId",config.getAppId());
        reqObj.put("sign",sign(request.getAuthItem(),timestamp,sequenceNo));
        reqObj.put("timestamp",timestamp);
        reqObj.put("sequenceNo",sequenceNo);
        reqObj.put("authItem",request.getAuthItem());
        reqObj.put("name",request.getName());
        reqObj.put("phone",request.getMobile());
        reqObj.put("idcard",request.getIdCard());
        if(!StringUtils.isEmpty(request.getPlatform())){
            reqObj.put("platform",request.getPlatform());
        }

        //调用
        try {
            String res = HttpUtil.postJson(config.getTokenUrl(),reqObj);
            JSONObject result = JSONObject.parseObject(res);
            if(result.getInteger("retCode") == 1){
                return ResponseFactory.success(result.getJSONObject("data"));
            }
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,result.getString("retMsg"),result);
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }



    public Response getToken(GxbRequest request){

        //组装参数
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sequenceNo =  TracerContextUtil.getTraceId();
        JSONObject reqObj = new JSONObject();
        reqObj.put("appId",config.getAppId());
        reqObj.put("sign",sign(request.getAuthItem(),timestamp,sequenceNo));
        reqObj.put("timestamp",timestamp);
        reqObj.put("sequenceNo",sequenceNo);
        reqObj.put("authItem",request.getAuthItem());
        reqObj.put("name",request.getName());
        reqObj.put("phone",request.getMobile());
        reqObj.put("idcard",request.getIdCard());

        //调用
        try {
            String res = HttpUtil.postJson(config.getTokenUrl(),reqObj);
            JSONObject result = JSONObject.parseObject(res);
            if(result.getInteger("retCode") == 1){
                return ResponseFactory.success(result.getJSONObject("data"));
            }
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,result.getString("retMsg"),result);
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }

    @ApiMapping(value="gongxinbao.authorized",desc = "公信宝.授权")
    public Response authorized(GxbRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null || StringUtils.isEmpty(request.getReturnUrl()))
            return response;
        if(StringUtils.isEmpty(request.getReturnUrl())){
            return response.fail(SystemErrorCodeEnum.JSS_PARAM_CHECK_FAILED.getErrorCode(),"支付宝回跳应用的地址不能为空");
        }

        JSONObject object = new JSONObject();
        String key = String.format(GONGXINBAO_TOKEN, request.getMobile(), request.getIdCard());
        String token = redisCache.get(key);
        if(StringUtils.isEmpty(token)){
            request.setAuthItem("zhimaScore");
            response = getToken(request);
            if(!response.getCode().equals("200")){
                  return response;
            }
            JSONObject jsonObject =(JSONObject) response.getData();
            token = jsonObject.getString("token");
            redisCache.set(key,token,30, TimeUnit.MINUTES);
        }
        object.put("token",token);
        object.put("returnUrl",request.getReturnUrl());
        try {
            String res = HttpUtil.postJson(config.getAuthorizedUrl(),object);
            return getResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }


    @ApiMapping(value = "gongxinbao.getZhimaScore",desc = "公信宝.获取芝麻分")
    public Response getZhimaScore(GxbRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;

        String key = String.format(GONGXINBAO_TOKEN, request.getMobile(), request.getIdCard());
        String token = redisCache.get(key);
        try {
            String timestamp = String.valueOf(System.currentTimeMillis());
            String sequenceNo =  TracerContextUtil.getTraceId();
            StringBuffer url = new StringBuffer();
            url.append(config.getZhimaScoreUrl());
            url.append(token+"?");
            url.append("appId="+config.getAppId());
            url.append("timestamp="+timestamp);
            url.append("sign="+sign("zhimaScore",timestamp,sequenceNo));
            String res = HttpUtil.get(url.toString());
            return getResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }



    private Response  getResult (String res){
        JSONObject result = JSONObject.parseObject(res);
        String msg = result.getString("retMsg");
        if(result.getInteger("retCode") == 1){
            return ResponseFactory.success(result.getJSONObject("data"));
        }
        return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR.getErrorCode(),msg);
    }

    @ApiMapping(value = "gongxinbao.getRawdata",desc = "公信宝.获取原始数据")
    public Response getRawdata(GxbDataRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;
        String timestamp = String.valueOf(System.currentTimeMillis());
        String url = config.getRawdataUrl() + String.format(paramStr,request.getToken(),config.getAppId(),timestamp,sign(timestamp));
        return getImpl(url,request.getAuthItem());
    }

    @ApiMapping(value = "gongxinbao.getReport",desc = "公信宝.公信宝报表数据")
    public Response getReport(GxbDataRequest request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;

        String timestamp = String.valueOf(System.currentTimeMillis());
        String url = config.getReportUrl() + String.format(paramStr,request.getToken(),config.getAppId(),timestamp,sign(timestamp));
        return getImpl(url,request.getAuthItem());
    }

    private Response getImpl(String url,String authItem){
        String res = null;
        try {
            res = HttpUtil.get(url);
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }

        JSONObject result = JSONObject.parseObject(res);
        if(result.getInteger("retCode") == 1){
            String path = "$.data.authInfoVo.authItem";
            if(JSONPath.contains(result,path)){
                String authItem2 = (String)JSONPath.eval(result,path);
                if(!authItem.equals(authItem2)){
                    return ResponseFactory.fail(SystemErrorCodeEnum.JSS_PARAM_CHECK_FAILED,"入参与出参中的authItem不一致，authItem入参："+authItem2+",出参："+authItem);
                }
            }
            return ResponseFactory.success(result);
        }else{
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_ERROR,result.getString("retMsg"),result);
        }
    }

    private String sign(String authItem,String timestamp,String sequenceNo){
        return DigestUtils.md5Hex(String.format("%s%s%s%s%s", config.getAppId(), config.getAppSecurity(), authItem, timestamp, sequenceNo));
    }

    private String sign(String timestamp){
        String str = String.format("%s%s%s", config.getAppId(), config.getAppSecurity(), timestamp);
        return DigestUtils.md5Hex(str.getBytes());
    }
}
